/**
 * @copyright (c) YX Company.
 */
package com.ry.core.base.controller;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.CustomNumberEditor;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
import org.springframework.web.servlet.support.RequestContextUtils;

import com.ry.core.base.common.Page;
import com.ry.core.base.model.BaseModel;
import com.ry.core.base.model.SimpleModel;
import com.ry.core.base.service.IBaseService;
import com.ry.core.exception.BaseException;
import com.ry.core.exception.BusinessException;
import com.ry.core.util.ArrayUtils;
import com.ry.core.util.JsonUtils;
import com.ry.core.util.StringUtils;

/**
 * 控制层基类 ，所有业务类都应该继承此类
 * 
 * @author chengl
 * @Date 2011-8-16
 * @version 1.0
 */
public abstract class BaseController<T extends SimpleModel> extends
		MultiActionController {

	public static Logger logger = Logger.getLogger(BaseController.class);

	private static final char SP = '/';// File.separatorChar;

	private static final String JS = "js";

	private static final String CSS = "css";

	private static final String VIEW = "/view";

	private static final String VIEWCOMMONPATH = "/view/common";

	protected static final String VIEWSUCCESS = "common/success";

	protected ResultObj resultObj = new ResultObj();// 封装一个统一对象用于返回前台

	protected Map<String, Object> m = new HashMap<String, Object>();// 用来设置给前台显示map

	private static String[] excludeSearchArr = new String[] { "page",
			"pageSize", "dir", "sort" };// 搜索排除值

	public BaseController() {
	}

	/**
	 * 获取实体服务类的实例
	 * 
	 * @return
	 */
	public abstract IBaseService getEntityService();

	/**
	 * 前台指与对象之间的类型转换
	 * 
	 * @param binder
	 * @param request
	 */
	@InitBinder
	public void initBinder(WebDataBinder binder, WebRequest request) {
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		dateFormat.setLenient(false);
		binder.registerCustomEditor(Date.class, new CustomDateEditor(
				dateFormat, true));
		binder.registerCustomEditor(String.class,
				new StringTrimmerEditor(false));
		binder.registerCustomEditor(BigDecimal.class, new CustomNumberEditor(
				BigDecimal.class, true));
		binder.registerCustomEditor(Integer.class, null,
				new CustomNumberEditor(Integer.class, null, true));
		binder.registerCustomEditor(int.class, null, new CustomNativeEditor(
				Integer.class, null, true));
		binder.registerCustomEditor(Long.class, null, new CustomNumberEditor(
				Long.class, null, true));
		binder.registerCustomEditor(long.class, null, new CustomNativeEditor(
				Long.class, null, true));
		binder.registerCustomEditor(Float.class, new CustomNumberEditor(
				Float.class, true));
		binder.registerCustomEditor(Double.class, new CustomNumberEditor(
				Double.class, true));
		binder.registerCustomEditor(BigInteger.class, new CustomNumberEditor(
				BigInteger.class, true));

	}

	/**
	 * 跳转到列表页面
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping
	public ModelAndView toList(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		getSearchMap(request);
		return view("list");
	}

	@RequestMapping
	public ModelAndView listJsonp(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		getSearchMap(request);
		List<?> list = getEntityService().findListByMap(m);
		ModelAndView mv = new ModelAndView("common/jsonp");
		String s = JsonUtils.listToJson(list);
		mv.addObject("list", s);
		return mv;
	}

	/**
	 * 获取列表数据(分页)
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping
	@ResponseBody
	public Page<?> list(Page<?> page, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		try {
			getSearchMap(request);
			page = getEntityService().getPage(page, m);
		} catch (Exception e) {
			throw new Exception(e);
		}
		return page;
	}

	/**
	 * 把搜索值转为map，供后台及界面使用
	 * 
	 * @param request
	 * @return
	 */
	public Map<String, Object> getSearchMap(HttpServletRequest request) {
		Map map = request.getParameterMap();
		for (Object key : map.keySet()) {
			String keyStr = key.toString();
			if (keyStr != "")
				if (!ArrayUtils.isInArray(excludeSearchArr, keyStr)) {
					try {
						m.put(keyStr, java.net.URLDecoder.decode(
								request.getParameter(key.toString()), "UTF-8"));
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}
				}
		}
		return m;
	}

	/**
	 * 获取列表数据(不分页)
	 * 
	 * @param model
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping
	@ResponseBody
	public ResultObj listAllToJson(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		try {
			getSearchMap(request);
			List<?> list = getEntityService().findListByMap(m);
			resultObj.setCollection(list);
		} catch (Exception e) {
			throw new Exception(e);
		}
		return resultObj;
	}

	/**
	 * 获取列表数据(不分页)
	 * 
	 * @param model
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping
	public ModelAndView listAll(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		try {
			getSearchMap(request);
			List<?> list = getEntityService().findListByMap(m);
			m = new HashMap<String, Object>();
			m.put("list", list);
		} catch (Exception e) {
			throw new Exception(e);
		}
		return view("list");
	}

	/**
	 * 跳转到新增页面
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping
	public ModelAndView toAdd(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		getSearchMap(request);
		setLoginInfo(request);
		return view("add");
	}

	/**
	 * 新增业务对象
	 * 
	 * @param obj
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping
	public ModelAndView add(T obj, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		request.setAttribute("entry", obj);
		String validateInfo = this.validation(request, "add");
		if (!StringUtils.isEmpty(validateInfo)) {
			throw new Exception(validateInfo);
		}
		// setObjCreateInfo(request, obj);
		getEntityService().add(obj);
		m.put("msg", "保存成功。");
		return viewfull(VIEWSUCCESS);
	}

	/**
	 * 新增业务对象并返回对象
	 * 
	 * @param obj
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping
	@ResponseBody
	public T add2Obj(T obj, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		request.setAttribute("entry", obj);
		setObjCreateInfo(request, obj);
		getEntityService().add(obj);
		return obj;
	}

	/**
	 * 新增业务对象并返回id
	 * 
	 * @param obj
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping
	@ResponseBody
	public String add2Id(T obj, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		request.setAttribute("entry", obj);
		setObjCreateInfo(request, obj);
		getEntityService().add(obj);
		return obj.getId();
	}
	
	@RequestMapping
	public ModelAndView add2IdJsonp(T obj, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		request.setAttribute("entry", obj);
		setObjCreateInfo(request, obj);
		getEntityService().add(obj);
		ModelAndView mv = new ModelAndView("common/jsonp");
		mv.addObject("list", "'"+obj.getId()+"'");
		return mv;
	}

	/**
	 * 跳转到编辑页面
	 * 
	 * @param id
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping
	public ModelAndView toEdit(String id, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		SimpleModel obj = getEntityService().get(id);
		m.put(getClassModelName(), obj);
		setLoginInfo(request);
		return view("edit");
	}

	/**
	 * 编辑业务对象
	 * 
	 * @param obj
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping
	public ModelAndView edit(T obj, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		request.setAttribute("entry", obj);
		String validateInfo = this.validation(request, "edit");
		if (!StringUtils.isEmpty(validateInfo)) {
			throw new Exception(validateInfo);
		}
		try {
			// setObjEditInfo(request, obj);
			getEntityService().edit(obj);
			m.put("msg", "保存成功。");
		} catch (BusinessException e) {
			logger.error(BaseException.toString(e));
			throw new BusinessException(e.getMessage() != null ? e.getMessage()
					: "编辑失败", e);
		} catch (Exception e) {
			logger.error(BaseException.toString(e));
			throw new Exception(e.getMessage() != null ? e.getMessage()
					: "编辑失败", e);
		}
		return viewfull(VIEWSUCCESS);
	}

	/**
	 * 编辑业务对象某个属性
	 * 
	 * @param obj
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping
	@ResponseBody
	public boolean editObj(T obj, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		request.setAttribute("entry", obj);
		setObjEditInfo(request, obj);
		getEntityService().editObj(obj);
		return true;
	}

	/**
	 * 跳转到查看页面
	 * 
	 * @param id
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping
	public ModelAndView toView(String id, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		getSearchMap(request);
		SimpleModel obj = getEntityService().get(id);
		m.put(getClassModelName(), obj);
		setLoginInfo(request);
		return view("view");
	}

	/**
	 * 删除业务对象
	 * 
	 * @param ids
	 * @return 成功返回删除的记录数，不成功返回异常信息
	 */
	@RequestMapping
	@ResponseBody
	public ResultObj deletes(String ids, HttpServletRequest request,
			HttpServletResponse response) {
		String validateInfo = this.validation(request, "delete");
		if (!StringUtils.isEmpty(validateInfo)) {
			resultObj.setSuccess(false);
			resultObj.setMsg(validateInfo);
			return resultObj;
		}
		try {
			// 已删除记录数
			int deleteNum = getEntityService().removeByIds(ids);
			resultObj.setMsg(String.valueOf(deleteNum));

		} catch (Exception e) {
			logger.error(BaseException.toString(e));
			resultObj.setSuccess(false);
			resultObj.setMsg(e.getMessage() == null ? "删除失败" : e.getMessage());
		}
		return resultObj;
	}

	/**
	 * 删除单条记录
	 * 
	 * @param id
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping
	@ResponseBody
	public ResultObj delete(String id, HttpServletRequest request,
			HttpServletResponse response) {
		try {
			// 已删除记录数
			int deleteNum = getEntityService().remove(id);
			resultObj.setMsg(String.valueOf(deleteNum));
		} catch (Exception e) {
			logger.error(BaseException.toString(e));
			resultObj.setSuccess(false);
			resultObj.setMsg(e.getMessage() == null ? "删除失败" : e.getMessage());
		}
		return resultObj;
	}

	/**
	 * 跳转到高级搜索页面
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping
	public ModelAndView toSearch(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		getSearchMap(request);
		setLoginInfo(request);
		return view("search");
	}

	/**
	 * 跳转到视图页面，具有业务规则，通过控制类的包名及类名自动解析视图路径
	 * 
	 * @param map
	 *            替换的map，前台通过key获取值
	 * @param url
	 *            模板路径 <br>
	 *            替换规则：业务包名/业务名-url 如传入customer模块传入
	 *            list，则自动替换为customer/customer-list
	 * @return
	 * @throws BusinessException
	 */
	public ModelAndView view(String url) throws Exception {
		String businessPack = getBusinessPack();
		String className = getClassModelName();
		url = businessPack + SP + className + "-" + url;
		m.put("js", VIEW + SP + businessPack + SP + JS);
		return viewfull(url);
	}

	/**
	 * 跳转到视图页面，没有业务规则，需要传入完整的url
	 * 
	 * @param url
	 *            跳转页面路径
	 * @return
	 */
	public ModelAndView viewfull(String url) {

		ModelAndView mv = new ModelAndView(url);
		mv.addObject("viewCommonPath", VIEWCOMMONPATH);
		mv.addObject("jsCommon", SP + JS);
		mv.addObject("cssCommon", SP + CSS);
		if (m != null) {
			for (String key : m.keySet()) {
				mv.addObject(key, m.get(key));
			}
		}
		return mv;
	}

	/**
	 * 获取业务包名
	 * 
	 * @return
	 * @throws BusinessException
	 */
	public String getBusinessPack() throws Exception {
		String packagePath = this.getClass().getPackage().getName();
		int controllerIndex = packagePath.indexOf("controller");
		if (controllerIndex == -1) {
			throw new BusinessException("控制层包名不包含controller.");
		}
		String p = packagePath.substring(0, controllerIndex - 1);
		int lastPotinIndex = p.lastIndexOf('.');
		String p2 = p.substring(lastPotinIndex + 1);
		p = packagePath.substring(0, lastPotinIndex);
		lastPotinIndex = p.lastIndexOf('.');
		String p1 = p.substring(lastPotinIndex + 1);
		return p1 + SP + p2;
	}

	/**
	 * 获取业务名称
	 * 
	 * @return
	 */
	public String getClassModelName() {
		String n = this.getClass().getSimpleName().replace("Controller", "");
		return n.substring(0, 1).toLowerCase() + n.substring(1);
	}

	/**
	 * 验证方法，由业务类进行复写
	 * 
	 * @param request
	 * @param operate
	 *            操作类型，新增：add,修改：edit,删除：delete
	 * @return
	 */
	public String validation(HttpServletRequest request, String operate) {
		if (operate.equals("delete")) {
			if (StringUtils.isEmpty(request.getParameter("ids"))) {
				return "请求参数为空，禁止删除";
			}
		}
		return "";
	}

	/**
	 * 设置对象创建信息
	 * 
	 * @param obj
	 */
	public void setObjCreateInfo(HttpServletRequest request, T obj) {
		// if (obj instanceof BaseModel) {
		// BaseModel o = (BaseModel) obj;
		// o.setCreateId(getLoginUserId(request));
		// o.setCreateName(getLoginUserAccount(request));
		// o.setCreateTime(new Date());
		// setObjEditInfo(request, obj);
		// }
	}

	/**
	 * 设置对象修改信息
	 * 
	 * @param obj
	 */
	public void setObjEditInfo(HttpServletRequest request, T obj) {
		// if (obj instanceof BaseModel) {
		// BaseModel o = (BaseModel) obj;
		// o.setUpdateId(getLoginUserId(request));
		// o.setUpdateName(getLoginUserAccount(request));
		// o.setUpdateTime(new Date());
		// }
	}

	/**
	 * 设置当前登录人信息
	 */
	public void setLoginInfo(HttpServletRequest request) {
		// m.put("loginUser", getLoginUser(request));
		// m.put("loginUserId", getLoginUserId(request));
		// m.put("loginUserAccount", getLoginUserAccount(request));
		// m.put("loginDeptId", getLoginUserDeptId(request));
		// m.put("loginDeptName", getLoginUserDeptName(request));
		// m.put("loginUserName", getLoginUserName(request));
	}

	// ***********以下为获取当前登录用户信息方法*********************//

	/**
	 * 获取当前登录用户信息
	 * 
	 * @param request
	 * @return
	 */
	// public User getLoginUser(HttpServletRequest request) {
	// return (User) request.getSession().getAttribute("curUser");
	// }

	/**
	 * 获取当前登录用户id
	 * 
	 * @param request
	 * @return
	 */
	public String getLoginUserId(HttpServletRequest request) {
		return request.getSession().getAttribute("userId").toString();
	}

	/**
	 * 获取当前登录用户账号
	 * 
	 * @param request
	 * @return
	 */
	public String getLoginUserAccount(HttpServletRequest request) {
		return request.getSession().getAttribute("account").toString();
	}

	/**
	 * 获取当前登录用户姓名
	 * 
	 * @param request
	 * @return
	 */
	public String getLoginUserName(HttpServletRequest request) {
		return request.getSession().getAttribute("userName").toString();
	}

	/**
	 * 获取当前登录用户部门id
	 * 
	 * @param request
	 * @return
	 */
	public String getLoginUserDeptId(HttpServletRequest request) {
		return request.getSession().getAttribute("deptId").toString();
	}

	/**
	 * 获取当前登录用户部门名称
	 * 
	 * @param request
	 * @return
	 */
	public String getLoginUserDeptName(HttpServletRequest request) {
		return request.getSession().getAttribute("deptName").toString();
	}

	/**
	 * 获取登陆用户角色id数组
	 * 
	 * @param request
	 * @return
	 */
	public String[] getLoginUserRolesId(HttpServletRequest request) {
		return (String[]) request.getSession().getAttribute("rolesId");
	}

	/**
	 * 获取容器上下文
	 * 
	 * @param request
	 * @return
	 */
	public WebApplicationContext getContext(HttpServletRequest request) {
		return RequestContextUtils.getWebApplicationContext(request);
	}

	/**
	 * 校验唯一
	 * 
	 * @return
	 */
	@RequestMapping
	@ResponseBody
	public String checkRepeat(HttpServletRequest request) throws Exception {
		String validateId = request.getParameter("validateId");
		String validateError = request.getParameter("validateError");
		return "{'jsonValidateReturn':['" + validateId + "','" + validateError
				+ "','true']}";
	}
}
